package com.yanqu.road.server.manger.activity.commonteam;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.dao.impl.servercenter.ActivityDaoImpl;
import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.commonteam.CommonTeamConfigData;
import com.yanqu.road.entity.activity.commonteam.config.ActivityTeamConfig;
import com.yanqu.road.entity.activity.doublespring.DoubleSpringActivityConfig;
import com.yanqu.road.entity.activity.sonhai.config.SonHaiConfig;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.exception.BusinessException;
import com.yanqu.road.logic.bussiness.servercenter.ActivityBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.logic.helper.UnionActivityGroupHelper;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.activity.CommonTeamProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.commonteam.CommonTeamModule;
import com.yanqu.road.server.gameplayer.module.activity.doublespring.DoubleSpringActivityModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PreReduceModule;
import com.yanqu.road.server.manger.ForbiddenWordMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.activity.commonteam.activitytypehandler.CommonTeamActivityTypeStrategy;
import com.yanqu.road.server.manger.activity.commonteam.activitytypehandler.handler.CommonTeamSonHaiStrategy;
import com.yanqu.road.server.manger.activity.commonteam.activitytypehandler.handler.XingYouShanShuiStrategy;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.union.GameUnionActivityGroupMgr;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CommonTeamMgr extends TempMgr {

    /**
     * 日志
     */
    private static Logger logger = LogManager.getLogger(CommonTeamMgr.class.getName());

    /**
     * 配置MAP
     */
    private static Map<Integer, CommonTeamConfigData> configDataMap = new ConcurrentHashMap<>();

    /**
     * 活动类型策略MAP(该策略map可以灵活处理不同活动类型的特殊处理)
     */
    private static Map<Integer, CommonTeamActivityTypeStrategy> activityTypeStrategyMap = new ConcurrentHashMap<>();
    static {
        activityTypeStrategyMap.put(eActivityType.SonHai.getValue(), new CommonTeamSonHaiStrategy());
        activityTypeStrategyMap.put(eActivityType.XingYouShanShui.getValue(), new XingYouShanShuiStrategy());
    }

    @Override
    public boolean init() throws Exception {
        return true;
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    /**
     * 加载活动配置
     */
    public static void reloadActivityData() {
        getLogger().info("reload CommonTeam Activity start");
        //获取活动
        List<ActivityInfo> activityList = NormalActivityMgr.getOpenActivityInfoListByTypeSet(activityTypeStrategyMap.keySet());
        Map<Integer, CommonTeamConfigData> newConfigMap = new ConcurrentHashMap<>();
        for (ActivityInfo activityInfo: activityList) {
            //获取组队配置
            CommonTeamConfigData config = getTeamConfigFromDb(activityInfo);
            if (config != null) {
                newConfigMap.put(activityInfo.getActivityId(), config);
            }
        }
        configDataMap = newConfigMap;
        //同步玩家
        for (GamePlayer player: GamePlayerMgr.getAllOnlinePlayer()) {
            player.getModule(CommonTeamModule.class).syncConfig();
        }
        getLogger().info("reload CommonTeam Activity end");
    }

    /**
     * 获取配置MAP
     * @return
     */
    public static Map<Integer, CommonTeamConfigData> getConfigDataMap() {
        return configDataMap;
    }

    /**
     * 获取配置
     * @param activityId
     * @return
     */
    public static CommonTeamConfigData getActivityConfig(int activityId) {
        return configDataMap.get(activityId);
    }

    /**
     * 获取通用组队配置（读DB）
     * @param activityInfo
     * @return
     */
    public static CommonTeamConfigData getTeamConfigFromDb(ActivityInfo activityInfo) {
        int activityId = activityInfo.getActivityId();
        Map<String, ActivityTeamConfig> activityTeamConfigMap = new ActivityDaoImpl().getActivityTeamConfigMap(activityId);
        if (activityTeamConfigMap == null || activityTeamConfigMap.isEmpty()) {
            logger.error("加载通用组队配置-组队配置未找到：{}", activityId);
            return null;
        }
        try {
            CommonTeamConfigData configData = new CommonTeamConfigData();
            configData.setActivityId(activityId);
            configData.setActivityInfo(activityInfo);
            int ingotsNum = activityTeamConfigMap.get("TEAM_CREATE_NEED_INGOTS").getIntValue();
            String teamCost = GameConfig.GAME_MONEY_INGOTS + "=" + ingotsNum;
            configData.setCreateTeamCost(teamCost);
            configData.setCreateNeedIngots(ingotsNum);
            configData.setCreateTeamTime(activityTeamConfigMap.get("TEAM_CREATE_TEAM_TIME").getIntValue());
            configData.setUserNumMax(4);
            configData.setNameLengthMax(activityTeamConfigMap.get("TEAM_NAME_LENGTH_LIMIT").getIntValue());
            configData.setApplyMax(activityTeamConfigMap.get("TEAM_APPLY_MAX_LIMIT").getIntValue());
            configData.setUserApplyMax(activityTeamConfigMap.get("TEAM_USER_APPLY_MAX_LIMIT").getIntValue());
            configData.setJoinCrossTeamFlag(activityTeamConfigMap.get("TEAM_JOIN_KUAFU").getIntValue());
            configData.setJoinCd(activityTeamConfigMap.get("TEAM_JOIN_CD").getIntValue());
            long endTime = activityInfo.getBeginTime() * 1000 + activityTeamConfigMap.get("TEAM_CREATE_TEAM_TIME").getIntValue() * DateHelper.MINUTE_MILLIONS;
            configData.setEndTime(endTime);
            //日志输出一下
            logger.info("加载通用组队配置：" + JSONObject.toJSONString(configData));
            return configData;
        } catch (Exception e) {
            logger.error("加载通用组队配置-报错：{}", e);
        }
        return null;
    }

    /**
     * 是否玩家可以进入活动
     * @param player
     * @return
     */
    public static int canEntryActivity(GamePlayer player, int activityId) {
        CommonTeamConfigData configData = getActivityConfig(activityId);
        if (configData == null) {
            return GameErrorCode.E_COMMON_TEAM_TEAM_ACTIVITY_NOT_EXIST;
        }
        if (!ActivityMgr.activityInShowTime(configData.getActivityInfo())) {
            return GameErrorCode.E_COMMON_TEAM_TEAM_ACTIVITY_NOT_EXIST;
        }
        if(!checkSystemUnlock(player, configData.getActivityInfo().getType())){
            return GameErrorCode.E_COMMON_TEAM_SYSTEM_NOT_UNLOCK;
        }
        return 0;
    }

    /**
     * 判断系统是否解锁，根据活动类型
     * @param player
     * @param activityType
     * @return
     */
    public static boolean checkSystemUnlock(GamePlayer player, int activityType) {
        CommonTeamActivityTypeStrategy strategy = activityTypeStrategyMap.get(activityType);
        if (strategy == null) {
            return false;
        }
        return strategy.checkSystemUnlock(player);
    }

    /**
     * 判断是否在组队期
     * @param activityId
     * @return
     */
    public static boolean checkInTeamTime(int activityId) {
        CommonTeamConfigData configData = configDataMap.get(activityId);
        if (configData == null) {
            return false;
        }
        long nowTime = System.currentTimeMillis();
        if (nowTime >= configData.getActivityInfo().getBeginTime() * 1000 && nowTime <= configData.getEndTime()) {
            return true;
        }
        return false;
    }

    /**
     * 检查活动类型
     * @param activityType
     * @return
     */
    public static boolean checkActivityType(int activityType) {
        return activityTypeStrategyMap.containsKey(activityType);
    }

    /**
     * 公用check
     * @param activityId
     * @throws BusinessException
     */
    public static void commonCheck(int activityId, long userId) throws BusinessException {
        ActivityInfo activityInfo = ActivityMgr.getOpenActivityInfo(activityId);
        if (activityInfo == null) {
            throw new BusinessException(GameErrorCode.E_ACTIVITY_NO_FOUND);
        }
        if (!ActivityHelper.activityInShowTime(activityInfo)) {
            throw new BusinessException(GameErrorCode.E_ACTIVITY_NO_FOUND);
        }
        CommonTeamConfigData configData = getActivityConfig(activityId);
        if (configData == null) {
            throw new BusinessException(GameErrorCode.E_ACTIVITY_NO_FOUND);
        }
        //判断是否在分组名单内
        int groupId = GameUnionActivityGroupMgr.getGroupId(activityId, userId);
        if (groupId == UnionActivityGroupHelper.NO_GROUP_ID) {
            throw new BusinessException(GameErrorCode.E_COMMON_TEAM_NOT_IN_GROUP);
        }
    }

    /********************************************交互方法**********************************************/

    /**
     * 获取队伍列表
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void getTeamList(GamePlayer player, CommonTeamProto.CommonTeamGetTeamListReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_GET_TEAM_LIST, reqMsg.toBuilder(), reqMsg.getActivityId());
    }

    /**
     * 创建队伍
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void createTeam(GamePlayer player, CommonTeamProto.CommonTeamCreateTeamReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        CommonTeamConfigData configData = getActivityConfig(reqMsg.getActivityId());
        CommonTeamProto.CommonTeamCreateTeamReqMsg.Builder builder = reqMsg.toBuilder();
        //获取一下道具是否足够
        Property cost = PropertyHelper.parseStringToProperty(configData.getCreateTeamCost());
        if (player.getModule(CurrencyModule.class).currencyIsEnough(cost)) {
            builder.setEnoughCost(true);
            // 预扣除
            player.getModule(PreReduceModule.class).preReduce(cost);
        } else {
            builder.setEnoughCost(false);
        }
        //校验队伍名称长度
        if (StringUtils.isNullOrEmpty(reqMsg.getTeamName()) || reqMsg.getTeamName().length() > configData.getNameLengthMax()) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NAME_ERROR);
        }
        //敏感字过滤
        if(ForbiddenWordMgr.isNickNameForbidden(reqMsg.getTeamName())){
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NAME_FORBIDDEN);
        }
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_CREATE_TEAM, builder, reqMsg.getActivityId());
    }

    /**
     * 创建队伍跨服返回
     * @param player
     * @param reqMsg
     */
    public static void createTeamFromCross(GamePlayer player, CommonTeamProto.CommonTeamCreateTeamRespMsg reqMsg) {
        CommonTeamProto.CommonTeamCreateTeamRespMsg.Builder builder = reqMsg.toBuilder();
        Property cost = PropertyHelper.parseStringToProperty(reqMsg.getCostProp());
        //删除预扣
        if (reqMsg.getNeedRePreCost()) {
            player.getModule(PreReduceModule.class).restorePreReduce(cost);
        }
        if (builder.getRet() == 0 && builder.getNeedCost()) {
            //扣除道具
            player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.Activity, eLogMoneyType.ActivityCommonTeamCreateTeamCost);
        }
        player.sendPacket(Protocol.U_COMMON_TEAM_CREATE_TEAM, builder);
    }

    /**
     * 获取队伍详情（根据队伍ID）
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void getTeamInfo(GamePlayer player, CommonTeamProto.CommonTeamGetTeamInfoReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_GET_TEAM_INFO, reqMsg.toBuilder(), reqMsg.getActivityId());
    }

    /**
     * 获取玩家数据
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void getUserData(GamePlayer player, CommonTeamProto.CommonTeamGetUserDataReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        CommonTeamProto.CommonTeamGetUserDataReqMsg.Builder builder = reqMsg.toBuilder();
        //获取玩家baseInf
        UserBaseInfo userBaseInfo = UserMgr.parseUserBaseInfo(player.getUserInfo(), GameServer.getInstance().getServerId());
        builder.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        //活动配置
        CommonTeamConfigData configData = getActivityConfig(reqMsg.getActivityId());
        //不同活动，战力取值不同。策略处理
        CommonTeamActivityTypeStrategy strategy = activityTypeStrategyMap.get(configData.getActivityInfo().getType());
        if (strategy == null) {
            throw new BusinessException(GameErrorCode.E_COMMON_TEAM_ACTIVITY_TYPE_NOT_COF);
        }
        long power = strategy.getPower(player, reqMsg.getActivityId());
        builder.setPower(power);
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_GET_USER_DATA, builder, reqMsg.getActivityId());
    }

    /**
     * 申请/撤销 加入队伍
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void applyJoinTeam(GamePlayer player, CommonTeamProto.CommonTeamApplyJoinTeamReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_APPLY_JOIN_TEAM, reqMsg.toBuilder(), reqMsg.getActivityId());
    }

    /**
     * 申请列表
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void getApplyList(GamePlayer player, CommonTeamProto.CommonTeamGetApplyListReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_GET_APPLY_LIST, reqMsg.toBuilder(), reqMsg.getActivityId());
    }

    /**
     * 同意加入队伍
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void agreeJoinTeam(GamePlayer player, CommonTeamProto.CommonTeamAgreeJoinTeamReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        CommonTeamProto.CommonTeamAgreeJoinTeamReqMsg.Builder reqMsgBuilder = reqMsg.toBuilder();
        reqMsgBuilder.setLanguage(player.getLanguage());
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_AGREE_JOIN_TEAM, reqMsgBuilder, reqMsgBuilder.getActivityId());
    }

    /**
     * 一键拒绝加入队伍
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void oneKeyReject(GamePlayer player, CommonTeamProto.CommonTeamOneKeyRejectReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_ONE_KEY_REJECT, reqMsg.toBuilder(), reqMsg.getActivityId());
    }

    /**
     * 退出队伍
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void quitTeam(GamePlayer player, CommonTeamProto.CommonTeamQuitTeamReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_QUIT_TEAM, reqMsg.toBuilder(), reqMsg.getActivityId());
    }

    /**
     * 踢出队伍
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void kickOutTeam(GamePlayer player, CommonTeamProto.CommonTeamKickOutTeamReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_KICK_OUT_TEAM, reqMsg.toBuilder(), reqMsg.getActivityId());
    }

    /**
     * 获取队伍聊天列表
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void getTeamChatMsgList(GamePlayer player, CommonTeamProto.CommonTeamGetChatListReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_GET_CHAT_MSG_LIST, reqMsg.toBuilder(), reqMsg.getActivityId());
    }

    /**
     * 获取队伍榜单
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void getTeamRankList(GamePlayer player, CommonTeamProto.CommonTeamGetRankListReqMsg reqMsg) throws BusinessException {
        commonCheck(reqMsg.getActivityId(), player.getUserId());
        //上跨服
        player.sendUnionActivityGroupPacket(CrossProtocol.C2_COMMON_TEAM_GET_RANK_LIST, reqMsg.toBuilder(), reqMsg.getActivityId());
    }
}
